<template>
  <div class="chat-container">
    <div class="chat-box" ref="scrollContainer">

      <div v-for="(message, index) in messages" :key="index">


        <div v-if="!message.isMe" class="message-wrapper-glm" ref="messageList">
          <!-- 添加头像或其他标识 -->
          <img v-if="message.avatar" src="../../picture/robot.svg" style="height: 40px;" class="chat-avar">
          <div v-if="!message.avatar" style="width: 40px;"></div>
          <div class="message gpt-message" :class="{ 'chat-code':message.codeMessage }">
              <pre>
                  <code style="white-space: pre-wrap;" v-html="message.formattedText "
                        :class="{ 'code':message.codeMessage }"></code>
              </pre>
            <!-- <div v-html="message.formattedText"></div> -->
            <!-- 加载指示器 -->
            <!-- <div v-if="this.isLoading" class="loading-indicator">...</div> -->
          </div>
        </div>


        <div v-if="message.isMe" class="message-wrapper-user" ref="messageList">
          <div class="ghost">
            <component :is="current_ghost"></component>
          </div>
          <div class="message bl-div user-message">
            {{ message.text }}
          </div>
        </div>

      </div>
    </div>
    <div class="last-element" ref="lastElement"></div>

    <div v-if="this.isLoading" class="loading">
      <component :is="current_loading"></component>
    </div>

  </div>
  <div class="input-container">
    <el-input
        v-model="userMessage"
        @keypress.enter="sendMessage"
        type="textarea"
        placeholder="Please input(alt + Enter = line break)"
        class="input"
        @keydown.alt.enter="handleAltEnter"
        :disabled="permission === null || permission === undefined"
    />
    <button class="bubbly-button" @click="sendMessage">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="50" height="50">
        <path fill="none" d="M3 3l9 6-9 6v-4l8.5-5.5L3 7z" stroke="#000" stroke-width="2"/>
      </svg>
    </button>
  </div>
</template>


<script>
/* eslint-disable */
import Ghost from '../CssPage/GhostView.vue';
import loading from '../CssPage/LoadingView.vue';

import Clipboard from 'clipboard';
import MarkdownIt from 'markdown-it';
import hljs from 'highlight.js';
/*黑色主题*/
import 'highlight.js/styles/atom-one-dark.css';
import {doGet} from "@/http/HttpRequest";
// import { ref } from 'vue'
// const loading = ref(true)

export default {
  props: ['dataFromHomePage', 'dataHomeName'],
  // 定义你想要接收的数据
  data() {
    return {
      permission: null ,
      isLoading: false, // 控制加载指示器的显示
      Message_display: 0,
      current_ghost: Ghost,
      current_loading: loading,
      userMessage: '',
      // formattedCode: '',

      messages: [
        {
          text: '',
          formattedText: "你好👋！我是人工智能助手，很高兴见到你，欢迎问我任何问题。",
          codeMessage: false,
          isMe: false,
          avatar: true
        },
      ],
      Send: {
        messages: {
          content: "",
          role: "user"
        },
        model: ""
        // GLM_3_5_TURBO
      },
    };
  },

  methods: {
    sendMessage() {
      if (!this.userMessage.trim()) return;
      // 发送用户消息
      this.messages.push({isMe: true, text: this.userMessage.trim()});
      // this.Message_display.push({ isChat: false });
      this.Send.messages.content = this.userMessage.trim()
      this.Send.model = this.dataFromHomePage
      this.userMessage = ''; // 清空输入框
      this.Message_display = 0; // 把代码部分的标记值置0
      this.isLoading = true; // 开始加载指示器

      // 发起HTTP请求
      fetch(
          // 'http://117.72.75.183:80/api/v1/chat/completions'
          'http://127.0.0.1:80/api/v1/chat/completions'
          , {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json;charset=utf-8',
              'Authorization': 'b8b6',
              'MzheartQ': localStorage.getItem('jwtToken'),
            },
            body: JSON.stringify(this.Send)
          })
          .then(resp => {
            if (resp.status === 401) {
              // 处理状态码 401，例如：跳转到登录页面
              window.location.href = '/';
              return;
            }
            const reader = resp.body.getReader(); // 获取响应流的读取器
            const decoder = new TextDecoder('utf-8'); // 创建文本解码器
            this.messages.push({isMe: false, text: '', formattedText: '', avatar: true});

            const readStream = () => {
              reader.read().then(({done, value}) => {
                if (done) {
                  console.log('Server-sent event stream closed'); // 服务器推送的事件流结束
                  this.isLoading = false; //停止加载指示器
                  return;
                }
                const decodedValue = decoder.decode(value, {stream: true}); // 解码流数据


                // 在这里处理纯文本数据，例如将其显示在页面上
                this.receiveMessage(decodedValue); // 处理接收到的文本数据
                readStream(); // 继续读取流数据
              });
            };

            readStream(); // 开始读取流数据

          })
          .catch(error => {
            console.error('Error:', error);
            this.isLoading = false; //停止加载指示器
          })
      ;

    },

    receiveMessage(newMessage) {
      // 假设 this.messages 是一个存储所有消息的数组
      // 假设最后一个消息对象已经存在且包含 text 属性

      // 获取最后一个消息对象
      const lastMessage = this.messages[this.messages.length - 1];
      lastMessage.text += newMessage

      const md = new MarkdownIt({
        html: true,
        linkify: true,
        typographer: true,
        highlight: function (str, lang) {
          // 当前时间加随机数生成唯一的id标识
          const codeIndex = parseInt(Date.now()) + Math.floor(Math.random() * 10000000)
          // 复制功能主要使用的是 clipboard.js
          let html = `<button class="copy-btn" type="button" data-clipboard-action="copy" data-clipboard-target="#copy${codeIndex}"><svg t="1718979842558" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2720" width="16" height="16"><path d="M256 736v32H128a32 32 0 0 1-32-32V128a32 32 0 0 1 32-32h544a32 32 0 0 1 32 32v64h-32V128H128v608h128zM768 257.184l0.32-0.32 160.544 157.6-1.504 1.536H928v480a32 32 0 0 1-32 32H352a32 32 0 0 1-32-32V288a32 32 0 0 1 32-32h416v1.184z m0 44.224V416h116.736L768 301.44zM736 288H352v608h544V448h-160V288z m-288 128h192v32h-192v-32z m0 160h352v32H448v-32z m0 160h352v32H448v-32z" fill="#e6e6e6" p-id="2721"></path></svg></button><br>`
          const linesLength = str.split(/\n/).length - 1
          // 生成行号
          let linesNum = '<span aria-hidden="true" class="line-numbers-rows">'
          for (let index = 0; index < linesLength; index++) {
            linesNum = linesNum + '<span></span>'
          }
          linesNum += '</span>'
          if (lang && hljs.getLanguage(lang)) {
            try {
              // highlight.js 高亮代码
              const preCode = hljs.highlight(lang, str, true).value
              html = html + preCode
              if (linesLength) {
                html += '<b class="name">' + lang + '</b>'
              }
              // 将代码包裹在 textarea 中，由于防止textarea渲染出现问题，这里将 "<" 用 "&lt;" 代替，不影响复制功能
              return `<pre class="hljs"><code>${html}</code>${linesNum}</pre><textarea style="position: absolute;top: -9999px;left: -9999px;z-index: -9999;" id="copy${codeIndex}">${str.replace(/<\/textarea>/g, '&lt;/textarea>')}</textarea>`
            } catch (error) {
              console.log(error)
            }
          }

          const preCode = md.utils.escapeHtml(str)
          html = html + preCode
          return `<pre class="hljs"><code>${html}</code>${linesNum}</pre><textarea style="position: absolute;top: -9999px;left: -9999px;z-index: -9999;" id="copy${codeIndex}">${str.replace(/<\/textarea>/g, '&lt;/textarea>')}</textarea>`
        }
      })


      const text = String(lastMessage.text);
      lastMessage.formattedText = md.render(text);
      // 滚动到底部
      // 更新复制按钮的目标元素
      this.$nextTick(() => {
        // 销毁旧的 ClipboardJS 实例
        if (this.clipboard) {
          this.clipboard.destroy();
        }
        // 创建一个新的 ClipboardJS 实例
        this.clipboard = new Clipboard('.copy-btn')
        // 复制成功失败的提示
        this.clipboard.on('success', (e) => {
          this.$message.success('复制成功')
        })
        this.clipboard.on('error', (e) => {
          this.$message.error('复制成功失败')
        })
        // 滚动到底部
        this.scrollToBottom();
      });
    },
    scrollToBottom() {
      // 获取最后一个元素
      const lastElement = this.$refs.lastElement;
      // 确保 lastElement 存在且是一个 DOM 元素
      if (lastElement && lastElement instanceof HTMLElement) {
        // 将最后一个元素滚动到可视区域内
        lastElement.scrollIntoView();
      }
    },
    handleAltEnter(event) {
      if (event.altKey && event.key === 'Enter') {
        event.preventDefault(); // Prevent default behavior of Enter key
        this.userMessage += '\n'; // Append newline character to userMessage
      } else {
        // Handle other keypress events or pass them through
      }
    },
    permissions() {
      // const user = {
      //   username: this.dataHomeName
      // }
      doGet("/api/v1/login/authentication", {username: this.dataHomeName}).then(resp => {
        if (resp.data.code === "0000") {
          this.permission = resp.data.data.permissions;
        }
      })
    }
  },

  created() {
    this.permissions();
  },

  updated() {
    // 在组件更新后执行滚动到底部操作
    this.scrollToBottom();
  },

  mounted() {
    this.$nextTick(() => {
      this.clipboard = new Clipboard('.copy-btn')


    });

    // 组件挂载时执行滚动到底部操作
    this.scrollToBottom();


  },

  destroyed() {
    this.clipboard.destroy()
  },

  watch: {
    // 监听 items 数组的变化，在变化时执行滚动到底部操作
    items() {
      this.scrollToBottom();
    }
  }


};
</script>

<style>
@import '/src/CSS/BorderLine.css';
@import '/src/CSS/BubbleButton.css';

.ghost {
  width: 40px;
  height: 40px;
  background: #000;
  border-radius: 50%; /* 将边框设为圆形 */
}

.chat-code {
  background-color: #000;
}

.code {
  color: aliceblue;
}

.loading {
  position: absolute;
  bottom: 10%;
  width: 20%;
  left: 50%;
  transform: translateX(-50%);
}


/* 根据消息的发送者，调整消息的布局 */
.message-wrapper-glm {
  display: flex; /* 使用 flexbox 布局 */
  justify-content: flex-start;
  width: 90%;
  margin: 0%;
  padding: 0;
  right: 0%;
  /* 线性渐变：从红色 (#ffcccc) 到浅绿色 (#ccffcc) */
  background: linear-gradient(to right, #f16d6d, #80de80),
    /* 径向渐变：从浅蓝色 (#ccccff) 到浅黄色 (#ffffcc) */ radial-gradient(circle, #7878e1, #ab88d5);
  background-blend-mode: screen; /* 叠加模式 */
  border-radius: 5px; /* 设置圆角 */
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* ChatGPT消息阴影 */
  flex-wrap: wrap; /* 允许子元素换行 */
}

.message-wrapper-glm .text {
  flex-grow: 1;
}

/* 根据消息的发送者，调整消息的布局 */
.message-wrapper-user {
  display: flex; /* 使用 flexbox 布局 */
  justify-content: flex-start;
  width: 100%;
  margin: 0;
  padding: 0;
}


.message {
  max-width: 80%;
  padding: 5px 5px 0px 3px;
  border-radius: 20px;
  display: inline-block;
  position: relative;
  color: #000000;
  border-radius: 5px; /* 设置圆角 */
  word-wrap: break-word !important;
  overflow-wrap: break-word !important;
}


.gpt-message {
  align-self: flex-start; /* GLM 消息位于行首 */
}

.user-message {
  margin: 30px;
}


/* 确保 .message 中的文本正确对齐 */
.message .text {
  text-align: left; /* 统一设置为 left */
  opacity: 0; /* 初始设置文字透明 */
  animation: fadeIn 0.5s forwards; /* 逐字显示动画 */
}

.message-wrapper-glm .message .text {
  text-align: left; /* 对于 GLM 消息 */
  opacity: 0; /* 初始设置文字透明 */
  animation: fadeIn 0.5s forwards; /* 逐字显示动画 */
  word-wrap: break-word;
  overflow-wrap: break-word;
}


@keyframes fadeIn {
  to {
    opacity: 1; /* 逐字显示动画的关键帧 */
  }
}

.chat-box {
  height: 88%;
  overflow-y: auto;
  /* border: 2px solid #000000; 设置边框的宽度、样式和颜色 */

}

.user-message {
  text-align: right;
  margin-bottom: 10px;
}

.gpt-message {
  text-align: left;
  margin-bottom: 10px;
}

.chat-container {
  position: relative;
  height: 100%; /* 设置容器高度 */
}

.input-container {
  position: absolute;
  bottom: 8px;
  width: 97%;
  left: 50%;
  transform: translateX(-50%);
}

.input {
  width: 80%;
  border-radius: 5px; /* 设置圆角 */
}

pre.hljs {
  padding: 12px 2px 12px 40px !important;
  border-radius: 5px !important;
  position: relative;
  font-size: 14px !important;
  line-height: 22px !important;
  overflow: hidden !important;
}

pre.hljs code {
  display: block !important;
  margin: 0 10px !important;
  overflow-x: auto !important;
}

pre.hljs code::-webkit-scrollbar {
  z-index: 11;
  width: 6px;
}

pre.hljs code::-webkit-scrollbar:horizontal {
  height: 6px;
}

pre.hljs code::-webkit-scrollbar-thumb {
  border-radius: 5px;
  width: 6px;
  background: #666;
}

pre.hljs code::-webkit-scrollbar-corner,
pre.hljs code::-webkit-scrollbar-track {
  background: #1E1E1E;
}

pre.hljs code::-webkit-scrollbar-track-piece {
  background: #1E1E1E;
  width: 6px;
}

pre.hljs .line-numbers-rows {
  position: absolute;
  pointer-events: none;
  top: 12px;
  bottom: 12px;
  left: 0;
  font-size: 100%;
  width: 40px;
  text-align: center;
  letter-spacing: -1px;
  border-right: 1px solid rgba(0, 0, 0, .66);
  user-select: none;
  counter-reset: linenumber;
}

pre.hljs .line-numbers-rows span {
  pointer-events: none;
  display: block;
  counter-increment: linenumber;
}

pre.hljs .line-numbers-rows span:before {
  content: counter(linenumber);
  color: #999;
  display: block;
  text-align: center;
}

pre.hljs b.name {
  position: absolute;
  top: 2px;
  right: 50px;
  z-index: 10;
  color: #999;
  pointer-events: none;
}

pre.hljs .copy-btn {
  position: absolute;
  top: 2px;
  right: 4px;
  z-index: 10;
  color: white;
  cursor: pointer;
  background-color: #050000;
  border: 0;
  border-radius: 2px;
}


</style>

